/* Copyright 2007-2008 dnAnalytics Project.
 *
 * Contributors to this file:
 * Patrick van der Velde
 * Marcus Cuda
 *
 * This file is part of dnAnalytics.  dnAnalytics is licensed under the 
 * Microsoft Public License. See License.txt for a complete copy of the
 * license.
 */
using System;
using System.IO;

namespace dnAnalytics.LinearAlgebra.IO
{
    /// <summary>
    /// Base class to read a single <see cref="Matrix"/> from a file or stream.
    /// </summary>
    public abstract class SingleMatrixReader : ISingleMatrixReader
    {
        /// <summary>
        /// Reads a <see cref="Matrix"/> from a file.
        /// </summary>
        /// <param name="file">The file to read the matrix from.</param>
        /// <param name="storageType">The <see cref="StorageType"/> for the new matrix.</param>
        /// <returns>A <see cref="Matrix"/> containing the data from the file. <see langword="null" /> is returned if the file is empty.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="file"/> is <see langword="null" />.</exception>
        /// <exception cref="IOException">If the file doesn't exist.</exception>
        /// <exception cref="FormatException">If a value is not a number or not in a valid format.</exception>
        /// <exception cref="OverflowException">If a value represents a number less than <see cref="Double.MinValue"/> or greater than <see cref="Double.MaxValue"/>.</exception>
        public Matrix ReadMatrix(string file, StorageType storageType)
        {
            if (file == null)
            {
                throw new ArgumentNullException("file", Properties.Resources.EmptyOrNull);
            }

            return ReadMatrix(File.OpenRead(file), storageType);
        }

        /// <summary>
        /// Reads a <see cref="Matrix"/> from a <see cref="Stream"/>.
        /// </summary>
        /// <param name="stream">The <see cref="Stream"/> to read the matrix from.</param>
        /// <param name="storageType">The <see cref="StorageType"/> for the new matrix.</param>
        /// <returns>A matrix containing the data from the <see cref="Stream"/>. <see langword="null" /> is returned if the <see cref="Stream"/> is empty.</returns>
        /// <exception cref="ArgumentNullException">If <paramref name="stream"/> is <see langword="null" />.</exception>
        /// <exception cref="FormatException">If a value is not a number or not in a valid format.</exception>
        /// <exception cref="OverflowException">If a value represents a number less than <see cref="Double.MinValue"/> or greater than <see cref="Double.MaxValue"/>.</exception>
        public Matrix ReadMatrix(Stream stream, StorageType storageType)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            return DoReadMatrix(stream, storageType);
        }

        /// <summary>
        /// Subclasses override this method to do the actual reading.
        /// </summary>
        /// <param name="stream">The <see cref="Stream"/> to read the matrix from.</param>
        /// <param name="storageType">The <see cref="StorageType"/> for the new matrix.</param>
        /// <returns>A matrix containing the data from the <see cref="Stream"/>. <see langword="null" /> is returned if the <see cref="Stream"/> is empty.</returns>
        protected abstract Matrix DoReadMatrix(Stream stream, StorageType storageType);
    }
}